if GameMode == nil then
    _G.GameMode = class({})
end



require('def')
require("http")
require("./utils/util")
require('./utils/color')
require(  './config/config' )
require('./utils/timer')
require('./utils/msg')
require('./utils/selection')
require('./ai/bot_ai')
require('events')
--require('filter')
require('abilities_shop')
require('hero')
require("item")
require('player')
require("map")
require('resources')
require("effect")
require("courier")
require("tower")
require("unit")
--require("spawner/creep_spawner")
--require("spawner/item_spawner")
require("spawner/boss_spawner")
require("talents")
require('./abilities/abilities')
CustomNetTables:SetTableValue(NetTableNames.game_config, "all",GameConfig)


function Activate()
    GameMode:InitGameMode()
end

function Precache( context )
    for _, v in pairs(ParticleNames) do
        PrecacheResource("particle",v, context)
    end

    for _, v in pairs(PreloadSounds) do
        PrecacheResource("soundfile", v, context)
    end
    PrecacheEveryThingFromKV(context)
end
function PrecacheEveryThingFromKV( context )
    local kv_files = {"scripts/npc/npc_units_custom.txt","scripts/npc/npc_abilities_custom.txt","scripts/npc/npc_heroes_custom.txt","scripts/npc/npc_abilities_override.txt","npc_items_custom.txt"}
    for _, kv in pairs(kv_files) do
        local kvs = LoadKeyValues(kv)
        if kvs then
            print("BEGIN TO PRECACHE RESOURCE FROM: ", kv)
            PrecacheEverythingFromTable( context, kvs)
        end
    end
end
function PrecacheEverythingFromTable( context, kvtable)
    for key, value in pairs(kvtable) do
        if type(value) == "table" then
            PrecacheEverythingFromTable( context, value )
        else
            if string.find(value, "vpcf") then
                PrecacheResource( "particle",  value, context)
                print("PRECACHE PARTICLE RESOURCE", value)
            end
            if string.find(value, "vmdl") then
                PrecacheResource( "model",  value, context)
                print("PRECACHE MODEL RESOURCE", value)
            end
            if string.find(value, "vsndevts") then
                PrecacheResource( "soundfile",  value, context)
                print("PRECACHE SOUND RESOURCE", value)
            end
        end
    end
end

function GameMode:InitGameMode()
    print( "GameMode:InitGameMode" )
    require('/config/game_mode')
    Item:Init()
    Http:Init()
    Player:Init()
    Hero:Init()
    Map:Init()
    AbilitiesShop:Init()
    BossSpawner:Init()
    Courier:Init()
    Unit:Init()
    Tower:Init()


    --GameRules:GetGameModeEntity():SetThink( "OnThink", self, 1 )
    --GameRules:GetGameModeEntity():SetModifyGoldFilter(Dynamic_Wrap(GameMode, 'GoldFilter'), self)
    --GameRules:GetGameModeEntity():SetModifyExperienceFilter(Dynamic_Wrap(GameMode, 'ExpFilter'), self)
    --ListenToGameEvent("player_reconnected", Dynamic_Wrap(GameMode, "OnReconnect"), self)
    ListenToGameEvent("player_disconnect", Dynamic_Wrap(GameMode, "OnDisconnect"), self)
    ListenToGameEvent("player_connect_full", Dynamic_Wrap(GameMode, "OnConnectFull"), self)
    ListenToGameEvent("npc_spawned",Dynamic_Wrap(GameMode,"OnNPCSpawned"),self)
    ListenToGameEvent("dota_player_gained_level",Dynamic_Wrap(GameMode,"OnPlayerGainedLevel"),self)
    ListenToGameEvent( "game_rules_state_change", Dynamic_Wrap( GameMode, 'OnGameRulesStateChange' ), self )
    ListenToGameEvent('entity_killed', Dynamic_Wrap(GameMode, 'OnEntityKilled'), self)
    ListenToGameEvent( "dota_item_picked_up", Dynamic_Wrap( GameMode, "OnItemPickUp"), self )
    --ListenToGameEvent( "dota_rune_activated_server", Dynamic_Wrap( GameMode, "OnRunePickUp"), self )



    --CustomGameEventManager:RegisterListener(GameEventNames.talent_manager_choose_talent, Dynamic_Wrap( GameMode, 'OnLearnTalent' ) )
    CustomGameEventManager:RegisterListener(GameEventNames.drag_ability, Dynamic_Wrap( GameMode, 'OnDragAbility' ) )
    CustomGameEventManager:RegisterListener(GameEventNames.buy_ability, Dynamic_Wrap( GameMode, 'OnBuyAbility' ) )
    CustomGameEventManager:RegisterListener(GameEventNames.refresh_ability, Dynamic_Wrap( GameMode, 'OnRefreshAbility' ) )
    CustomGameEventManager:RegisterListener(GameEventNames.add_bot, Dynamic_Wrap( GameMode, 'OnAddBot' ) )
    if IsInToolsMode() then
        require("cheat")
    end

end


function GameMode:KeepUpdateGameSetting()
    if GameRules:State_Get() == DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP then
        local hostPlayer = nil
        for playerId, playerInfo in pairs(Player.playerList) do
            local checkPlayer = PlayerResource:GetPlayer(playerId)
            if(checkPlayer ~= nil) then
                Player.playerList[playerId].teamId=checkPlayer:GetTeamNumber()
                if checkPlayer:IsNull() == false and playerInfo.isOnline == true then
                    if(table.containsKey(GameRules.G.teamColorList, checkPlayer:GetTeam()) == false) then
                        local teamId = Player:FindEmptyTeamForPlayer(playerId)
                        PlayerResource:SetCustomTeamAssignment(playerId, teamId)
                        Player.playerList[playerId].teamId=teamId
                    end
                    if(GameRules:PlayerHasCustomGameHostPrivileges(checkPlayer)) then
                        hostPlayer = checkPlayer
                    end
                end
            end
        end
        local botCount = 0
        if(hostPlayer ~= nil) then
            for playerId, playerInfo in pairs(Player.playerList) do
                    if(playerInfo.isBot==true) then
                        botCount = botCount + 1
                    end
                end
            CustomGameEventManager:Send_ServerToPlayer(hostPlayer,GameEventNames.update_bot, {count = botCount})
        end
        Timers:CreateTimer(0.5,function ()
            GameMode:KeepUpdateGameSetting()
        end)
    end
end



function GameMode:Test(param)
    --table.print(param)

    local hero=Hero.heroList[0]
    local hero2=Hero.heroList[1]
    --print(hero)
    local gameEvent = {}


    local particleName
    local soundName
    local firstBlood=false
    local attackerUnit={}
     attackerUnit.killingCount=0

    --DebugDrawBox(Vector(0, 0, 0), Vector(5, 5,0), Vector(500, 500, 0), 0, 255, 0, 180, 3)

    local flag=1

    --print(hero:GetBaseAttackTime())

    local rank=0

    Timers:CreateTimer(10,function ()
        rank=rank+50
        Player.playerList[hero:GetPlayerID()].rank=rank
        return 3
    end)



    --table.print(Player:GetSyncTable())

    --Timers:CreateTimer(2,function ()
    --    local courierUnit = PlayerResource:GetNthCourierForTeam(0, hero2:GetTeamNumber())
    --    courierUnit:ForceKill(true)
    --    flag=flag+1
    --    hero2=Hero.heroList[flag]
    --
    --    for i=0,7 do
    --        print(i,"  ",Player.playerList[i].modifyRank)
    --    end
    --    return 5
    --end)



    --for _,hero1 in pairs(Hero.heroList) do
    --    if hero1:GetPlayerID()~=0 then
    --        Player.playerList[hero1:GetPlayerID()].steamId=hero1:GetPlayerID()
    --        local courierUnit = PlayerResource:GetNthCourierForTeam(0, hero1:GetTeamNumber())
    --        courierUnit:ForceKill(true)
    --    end
    --
    --end


end



